﻿
/*********************************************************************
 ****  描    述： <线程管理类,缓存当前长期运行的(主要托管线程)的状态>
 ****  创 建 者： <周渊>
 ****  创建时间： <2014-03-19>
 ****  修改标识:  修改人: 周渊
 ****  修改日期:  2015-04-01
 ****  修改内容:   增加了 CycleCheckTasks 方法 修改StartCheckThreadStutes方法中的调用入口
*********************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Skybot.Base
{
    /// <summary>
    /// 线程管理类,缓存当前长期运行的(主要托管线程)的状态
    /// 主要包括:
    /// 1.协义解析线程
    /// 2.数据库操作线程
    /// 3.协义逻辑处理线程
    /// 等
    /// </summary>
    public class ThreadManager
    {
        #region 属性,字段定义
        /// <summary>
        /// 正在运行的应用的托管线程
        /// </summary>
        private List<TaskEx> tasks = new List<TaskEx>();



        /// <summary>
        /// 只读集合线程
        /// </summary>
        private System.Collections.ObjectModel.ReadOnlyCollection<TaskEx> _runingTasks = null;
        /// <summary>
        /// 只读集合线程
        /// </summary>
        public ReadOnlyCollection<TaskEx> RuningTasks
        {
            get
            {
                if (_runingTasks == null)
                {
                    _runingTasks = new ReadOnlyCollection<TaskEx>(tasks);
                }
                return _runingTasks;
            }
        }
        /// <summary>
        /// 运行结束的托管线程
        /// </summary>
        private List<TaskEx> stopedTask = new List<TaskEx>();

        /// <summary>
        /// 已经停止的只读集合线程
        /// </summary>
        private System.Collections.ObjectModel.ReadOnlyCollection<TaskEx> _stopTasks = null;
        /// <summary>
        /// 已经停止的只读集合线程
        /// </summary>
        public ReadOnlyCollection<TaskEx> StopedTask
        {
            get
            {
                if (_stopTasks == null)
                {
                    _stopTasks = new ReadOnlyCollection<TaskEx>(stopedTask);
                }
                return _stopTasks;
            }
        }

        /// <summary>
        /// 当前全局主要线程管理对像
        /// </summary>
        public static ThreadManager Instance
        {
            get { return instance; }
        }

        #endregion



        private static readonly ThreadManager instance = new ThreadManager();

        /// <summary>
        /// 将当前线程添加到线程管理对像
        /// </summary>
        /// <param name="task"></param>
        public void Add(TaskEx task)
        {
            //这里不用锁是因为 线程 很少启动
            tasks.Add(task);
        }

        /// <summary>
        /// 不在在外部实例化,构造函数
        /// </summary>
        private ThreadManager()
        {
            //开始线程检查
            StartCheckThreadStutes();
        }

        /// <summary>
        /// 检查线程状态
        /// </summary>
        protected void StartCheckThreadStutes()
        {
            TaskEx taskex = new TaskEx(CycleCheckTasks) { ThreadName = "ThreadManager管理线程", StartTime = DateTime.Now, AutoReRun = true };
            taskex.Start();
            tasks.Add(taskex);
        }
        /// <summary>
        /// 循环强制检查线程机制
        /// </summary>
        protected void CycleCheckTasks()
        {
            while(true)
            {
                DoWork();
            }
        }

        /// <summary>
        /// 检查线程状态,如果线程停止则进行重新启动
        /// </summary>
        protected void DoWork()
        {
            lock (tasks)
            {
                foreach (TaskEx task in tasks.ToArray())
                {
                    if (task.IsFaulted|| task.Status== TaskStatus.RanToCompletion )
                    {
                        if(task.Exception!=null)
                        {
                            //写日志
                           LogProvider.Create().Write(EventType.Error,"线程管理检测到线程异常退出::"+ task.Exception);
                        }
                        if (task.StartMethod != null&&task.AutoReRun)
                        {
                            //创建一个新的线程对像 重新启动线程
                            TaskEx newtask = new TaskEx(task.StartMethod)
                            {
                                StartTime = DateTime.Now,
                                ThreadName = task.ThreadName,
                                 AutoReRun =  task.AutoReRun,
                            };
                            newtask.Start();
                            Add(newtask);
                            LogProvider.Create().Write(EventType.Information, "运行异常停止的线程已经重新启动::" + newtask.ThreadName+"  "+task.StartTime);
                        }
                        //将失败的线程添加到已经停止的线程当中
                        stopedTask.Add(task);
                    }
                }
                //从当前正在运行的线程当中删除已经停止的线程对像
                foreach (TaskEx Ex in stopedTask)
                {
                    if (tasks.Contains(Ex))
                    {
                        tasks.Remove(Ex);
                    }
                }
            }
            System.Threading.Thread.Sleep(3 * 60 * 1000);

        }

    }
#if old
    /// <summary>
    /// 扩展的托管线程
    /// </summary>
    public class TaskEx : Task
    {
        #region 构造函数
        /// <summary>
        /// 使用指定的操作初始化新的 System.Threading.Tasks.Task。
        /// </summary>
        /// <param name="action"> 表示要在任务中执行的代码的委托。</param>
        public TaskEx(Action action)
            : base(action)
        {
            StartMethod = action;
        }

        /// <summary>
        /// 使用指定的操作和状态初始化新的 System.Threading.Tasks.Task。
        /// </summary>
        /// <param name="action">表示要在任务中执行的代码的委托</param>
        /// <param name="state">参数</param>
        public TaskEx(Action<object> action, object state)
            : base(action, state)
        {
        }

        #endregion

        /// <summary>
        /// 线程名
        /// </summary>
        public string ThreadName { get; set; }

        /// <summary>
        /// 线程启动开始时间
        /// </summary>
        public DateTime StartTime { get; set; }


        /// <summary>
        /// 运行结束时间,如果线程异常结束此时间为 线程管理填充时间
        /// </summary>
        public DateTime CheckStopTIme { get; set; }

        /// <summary>
        /// 线程执行失败后自动重新运行, 有延迟,需要 线程管理检查
        /// </summary>
        public bool AutoReRun { get; set; }

        /// <summary>
        /// 线程需要处理的方法 
        /// </summary>
        public Action StartMethod { get; protected set; }
    }
#endif

    /// <summary>
    /// 扩展的托管线程
    /// </summary>
    public class TaskEx : Task
    {
        #region 构造函数
        /// <summary>
        /// 使用指定的操作初始化新的 System.Threading.Tasks.Task。
        /// </summary>
        /// <param name="action"> 表示要在任务中执行的代码的委托。</param>
        public TaskEx(Action action)
            : base(action)
        {
            StartMethod = action;
        }

        /// <summary>
        /// 使用指定的操作和状态初始化新的 System.Threading.Tasks.Task。
        /// </summary>
        /// <param name="action">表示要在任务中执行的代码的委托</param>
        /// <param name="state">参数</param>
        public TaskEx(Action<object> action, object state)
            : base(action, state)
        {
        }
        /// <summary>
        /// 在观察取消标记时，使用指定的操作和 System.Threading.CancellationToken 初始化新的 System.Threading.Tasks.Task。
        /// </summary>
        /// <param name="action"> 表示要在任务中执行的代码的委托。</param>
        /// <param name="cancellationToken"> 新任务将观察的 System.Threading.CancellationToken。</param>
        public TaskEx(Action action, System.Threading.CancellationTokenSource cancellationToken)
            : base(action, cancellationToken.Token)
        {
            CanToKen = cancellationToken;
        }
        /// <summary>
        /// 使用指定的操作、状态和选项初始化新的 System.Threading.Tasks.Task。
        /// </summary>
        /// <param name="action">表示要在任务中执行的代码的委托</param>
        /// <param name="state">参数</param>
        /// <param name="cancellationToken"> 新任务将观察的 System.Threading.CancellationToken。</param>
        public TaskEx(Action<object> action, object state, CancellationTokenSource cancellationToken)
            : base(action, state, cancellationToken.Token)
        {
            CanToKen = cancellationToken;
        }

        #endregion

        /// <summary>
        /// 线程名
        /// </summary>
        public string ThreadName { get; set; }

        /// <summary>
        /// 线程启动开始时间
        /// </summary>
        public DateTime StartTime { get; set; }


        /// <summary>
        /// 运行结束时间,如果线程异常结束此时间为 线程管理填充时间
        /// </summary>
        public DateTime CheckStopTIme { get; set; }

        /// <summary>
        /// 线程执行失败后自动重新运行, 有延迟,需要 线程管理检查
        /// </summary>
        public bool AutoReRun { get; set; }

        /// <summary>
        /// 线程需要处理的方法 
        /// </summary>
        public Action StartMethod { get; protected set; }


        /// <summary>
        ///  任务将观察的 System.Threading.CancellationToken。
        /// </summary>
        public System.Threading.CancellationTokenSource CanToKen { get; protected set; }
    }
}
